<?php
/**
 * @table paysystems
 * @id abnamro
 * @title ABN-AMRO
 * @recurring cc
 * @am_payment_api 6.0
 */
class Am_Paysystem_Abnamro extends Am_Paysystem_CreditCard
{
    const PLUGIN_STATUS = self::STATUS_DEV;
    const PLUGIN_REVISION = '6.3.32';

    const SANDBOX_URL = "https://internetkassa.abnamro.nl/ncol/test/orderdirect.asp";
    const LIVE_URL = "https://internetkassa.abnamro.nl/ncol/prod/orderdirect.asp";

    const ABNAMRO_ALIAS = 'abnamro_alias';

    protected $defaultTitle = 'ABN-AMRO';
    protected $defaultDescription = 'Credit card payment';

    public function getFormOptions()
    {
        $ret = [self::CC_CODE, self::CC_ADDRESS, self::CC_COUNTRY, self::CC_CITY, self::CC_STREET, self::CC_ZIP, self::CC_PHONE];
        return $ret;
    }

    public function storesCcInfo()
    {
        return false;
    }

    public function isConfigured()
    {
        return strlen($this->getConfig('pspid')) && strlen($this->getConfig('userid')) && strlen($this->getConfig('pswd')) && strlen($this->getConfig('passphrase'));
    }

    public function _initSetupForm(Am_Form_Setup $form)
    {
        $form->addText("pspid")->setLabel('Your affiliation name in ABN-AMRO system')
            ->addRule('required');
        $form->addPassword('passphrase')->setLabel("SHA Passphrase\n" .
            'The passphrase is defined in the Merchant\'s Technical information,
            under the tab \'Data and Origin Verification\', section \'Checks for DirectLink\'')
            ->addRule('required');
        $form->addText('userid')->setLabel("Name of your application (API) user\n" .
            'Please refer to the ABN-AMRO User Manager documentation
            for information on how to create an API user')
            ->addRule('required');
        $form->addSecretText('pswd')->setLabel('Password of the API user (USERID)')
            ->addRule('required');
        $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled");
    }
    public function getSupportedCurrencies()
    {
        return ['EUR', 'USD', 'GBP', 'CHF'];
    }

    public function getRecurringType()
    {
        return self::REPORTS_CRONREBILL;
    }

    public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result)
    {
        $user = $invoice->getUser();
        if ($cc->user_id != $user->pk())
            throw new Am_Exception_Paysystem("Assertion failed: cc.user_id != user.user_id");
        if ($doFirst)
        {
            $tr = new Am_Paysystem_Transaction_Abnamro_Start($this, $invoice, $doFirst, $cc);
            $tr->run($result);
        }
        else
        {
            if(!$user->data->get(self::ABNAMRO_ALIAS))
                return $result->setFailed(["No saved ABN-AMRO alias for customer"]);
            $tr = new Am_Paysystem_Transaction_Abnamro_Recurring($this, $invoice, $doFirst, $cc);
            $tr->run($result);
        }
    }

}

class Am_Paysystem_Transaction_Abnamro extends Am_Paysystem_Transaction_CreditCard
{
    protected $parsedResponse = [];

    protected $user;

    protected $cc;

    public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, CcRecord $cc)
    {
        $request = new Am_HttpRequest($plugin->getConfig('testing') ? Am_Paysystem_Abnamro::SANDBOX_URL : Am_Paysystem_Abnamro::LIVE_URL,
            Am_HttpRequest::METHOD_POST);
        parent::__construct($plugin, $invoice, $request, $doFirst);
        $this->user = $invoice->getUser();
        $this->cc = $cc;
        $this->addRequestParams();
    }

    public function get_hash(array $vars)
    {
        $vars['amount'] = intval($vars['amount'] * 100);
        ksort($vars);
        $str='';
        $sign = $this->getPlugin()->getConfig('passphrase');
        foreach($vars as $k => $v)
        {
            $str.="{$k}={$v}$sign}";
        }
        return sha1($str);
    }

    public function run(Am_Paysystem_Result $result)
    {
        $this->request->addPostParameter('PSPID', $this->getPlugin()->getConfig('pspid'));
        $this->request->addPostParameter('USERID', $this->getPlugin()->getConfig('userid'));
        $this->request->addPostParameter('PSWD', $this->getPlugin()->getConfig('pswd'));
        $this->request->addPostParameter('Operation', 'SAL');
        $this->request->addPostParameter('amount', sprintf('%.2f', $this->getAmount()));
        $this->request->addPostParameter('currency', $this->invoice->currency);
        $this->request->addPostParameter('COM', $this->invoice->getLineDescription());
        $this->request->addPostParameter('OrderID', $this->invoice->public_id . '-' .($this->invoice->getPaymentsCount()+1));
        $alias = $this->doFirst ? ($this->user->name_f . $this->user->name_l . date("mdy")) : $this->user->data()->get(Am_Paysystem_Abnamro::ABNAMRO_ALIAS);
        $this->request->addPostParameter('ALIAS', $alias);
        $vars = $this->request->getPostParams();
        if($this->getPlugin()->getConfig('passphrase'))
        {
            $this->request->addPostParameter('SHASign', $this->get_hash($vars));
        }
        else
        {
            $strforsha = $vars['OrderID'] . $vars['amount'] . $vars['currency'] . $vars['CARDNO'] . $vars['PSPID'] . $vars['Operation'] . $vars['Mysecretsig'] . $vars["ALIAS"];
            $this->request->addPostParameter('SHASign', sha1($strforsha));
        }
        return parent::run($result);
    }

    protected function addRequestParams()
    {
    }

    public function getUniqId()
    {
        return $this->parsedResponse['PAYID'];
    }
    public function getReceiptId()
    {
        return $this->parsedResponse['PAYID'];
    }
    public function getAmount()
    {
        return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total;
    }
    public function parseResponse()
    {
        $parser = xml_parser_create();
        xml_parse_into_struct($parser, $this->response->getBody(), $vals, $index);
        xml_parser_free($parser);
        $this->parsedResponse = $vals[0]['attributes'];
    }

    public function validate()
    {
        if($this->parsedResponse['STATUS'] == '9' || $this->parsedResponse['NCERROR'] == '0' || $this->parsedResponse['NCSTATUS'] == '0')
        {
            $this->invoice->getUser()->data()->set(Am_Paysystem_Abnamro::ABNAMRO_ALIAS,$this->parsedResponse['ALIAS'])->update();
            $this->result->setSuccess($this);
        }
        else
            return $this->result->setFailed(["Transaction declined : ".$this->parsedResponse['NCERRORPLUS']]);
    }
}

class Am_Paysystem_Transaction_Abnamro_Start extends Am_Paysystem_Transaction_Abnamro
{
    function addRequestParams()
    {
        $this->request->addPostParameter('EMAIL', $this->invoice->getUser()->email);
        $this->request->addPostParameter('CARDNO', $this->cc->cc_number);
        $this->request->addPostParameter('ED', $this->cc->getExpire());
        $this->request->addPostParameter('CN', $this->cc->cc_name_f.' '.$this->cc->cc_name_l);
        $this->request->addPostParameter('CVC', $this->cc->getCvv());
        $this->request->addPostParameter('Ecom_Payment_Card_Verification', $this->cc->getCvv());
        $this->request->addPostParameter('Owneraddress', $this->cc->cc_street);
        $this->request->addPostParameter('OwnerZip', $this->cc->cc_zip);
        $this->request->addPostParameter('ownertown', $this->cc->cc_city);
        $this->request->addPostParameter('ownercty', $this->cc->cc_country);
        $this->request->addPostParameter('ownertelno', $this->cc->cc_phone);
    }

}

class Am_Paysystem_Transaction_Abnamro_Recurring extends Am_Paysystem_Transaction_Abnamro
{

}